//============================================================================
// Name        : Srtowanie.cpp
// Author      : Hanna Sienkiewicz 184184
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <cstdlib>
#include <string.h>
#include <fstream>
#include "Babelkowe.h"
#include "QuickSort.h"
#include "Kopiec.hh"
#include "Wstawianie.h"
using namespace std;

	Babelkowe* babelkowe= new Babelkowe();
	QuickSort* quicksort=new QuickSort();
	Kopiec* kopiec=new Kopiec();
	Wstawianie* wstawianie=new Wstawianie();

	typedef unsigned long long timestamp; // zmiena przechowujaca czas;

		// funkcja do mierzenia czasu
static timestamp gettimestamp(){
	struct timeval now;
	gettimeofday(&now,NULL);
	return now.tv_usec+(timestamp)now.tv_sec*1000000;
}

void wyswietl(int* t, int length){
	for(int i=0; i<length;i++){
		cout << t[i] << ", ";
	}
	cout << "\n\n";
}

double sprawdzQuicksort(int* tab, int size){
	timestamp t0=gettimestamp();
	quicksort->sortuj(tab,0,size-1);
	timestamp t1=gettimestamp();
	return (t1-t0)/1000000.0L;
}

double sprawdzKopiec(int* tab, int size){
	timestamp t0=gettimestamp();
	kopiec->settable(tab,size);
	kopiec->insert();
	kopiec->sort(tab,size);
	timestamp t1=gettimestamp();
	return (t1-t0)/1000000.0L;
}

double sprawdzWstawianie(int* tab, int size){
	timestamp t0=gettimestamp();
	wstawianie->sortuj(tab,size);
	timestamp t1=gettimestamp();
	return (t1-t0)/1000000.0L;
}

double sprawdzBabelkowe(int* tab, int size){
	timestamp t0=gettimestamp();
	babelkowe->sortuj(tab,size);
	timestamp t1=gettimestamp();
	return (t1-t0)/1000000.0L;
}

double* badania(double* w,int * tab, int n){
	int* tabpom;
	w[4]=n; // ilosc elementow dla kortych zostal zrobiony pomiar

	// babelkowo
	for(int i=0;i<1;i++){
		tabpom=new int[n];
		memcpy(tabpom,tab,sizeof(int)*n);
		w[0]+=sprawdzBabelkowe(tabpom,n);
		delete tabpom;
	}
//	w[0]/=10;
	cout << "Babelkowe: " << w[0] << " sek\n";

	//wstawianie
	for(int i=0;i<1;i++){
		tabpom=new int[n];
		memcpy(tabpom,tab,sizeof(int)*n);
		w[1]+=sprawdzWstawianie(tabpom,n);
		delete tabpom;
	}
//	w[1]/=10;
	cout << "Wstawianie: " << w[1] << " sek\n";

	// kopiec
	for(int i=0;i<1;i++){
		tabpom=new int[n];
		memcpy(tabpom,tab,sizeof(int)*n);
		w[2]+=sprawdzKopiec(tabpom,n);
		delete tabpom;
	}
//	w[2]/=10;
	cout << "Kopiec: " << w[2] << " sek\n";

	// quicksort
	for(int i=0;i<1;i++){
		tabpom=new int[n];
		memcpy(tabpom,tab,sizeof(int)*n);
		w[3]+=sprawdzQuicksort(tabpom,n);
		delete tabpom;
	}
//	w[3]/=10;
	cout << "QuickSort: " << w[3] << " sek\n\n";
	return w;
}

double* sprawdzwydajnosc(int n){
	cout << "\n\nSortowanie dla losowych elementow: " << n << "\n";
	double* w=new double[5];
	int* tab=new int[n];
	srand(time(0));
	for(int i=0;i<n;i++){
		tab[i]=rand()%n;
	}
	return badania(w,tab,n);
}

double* sprawdzwydajnoscOdwrotnie(int n){
	cout << "\n\nSortowanie dla odwrotniej kolejnosci elementow: " << n << "\n";
	double* w=new double[5];
	int* tab=new int[n];
	for(int i=0;i<n;i++){
		tab[i]=n-i;
	}
	return badania(w,tab,n);
}

void zapiszBabelkowe(double** w, int size){
	fstream plik( "bablkowe.txt", ios::out );
	    if( plik.good() )
	    {
	        for( int i = 0; i < size; i++ )
	        {
	            plik << w[i][0] << "\n";
	            plik.flush();
	        }
	        plik.close();
	    }
}

void zapiszWstawianie(double** w, int size){
	fstream plik( "wstawianie.txt", ios::out );
	    if( plik.good() )
	    {
	        for( int i = 0; i < size; i++ )
	        {
	            plik << w[i][1] << "\n";
	            plik.flush();
	        }
	        plik.close();
	    }
}

void zapiszKopiec(double** w, int size){
	fstream plik( "kopiec.txt", ios::out );
	    if( plik.good() )
	    {
	        for( int i = 0; i < size; i++ )
	        {
	            plik << w[i][2] << "\n";
	            plik.flush();
	        }
	        plik.close();
	    }
}

void zapiszQuickSort(double** w, int size){
	fstream plik( "quicksort.txt", ios::out );
	    if( plik.good() )
	    {
	        for( int i = 0; i < size; i++ )
	        {
	            plik << w[i][3] << "\n";
	            plik.flush();
	        }
	        plik.close();
	    }
}

void zapiszSkale(double** w, int size){
	fstream plik( "skala.txt", ios::out );
	    if( plik.good() )
	    {
	        for( int i = 0; i < size; i++ )
	        {
	            plik << w[i][4] << "\n";
	            plik.flush();
	        }
	        plik.close();
	    }
}

void zapiszNazwe(double** w, int size,int kolumna, string name){
	fstream plik( name.c_str(), ios::out );
		    if( plik.good() )
		    {
		        for( int i = 0; i < size; i++ )
		        {
		            plik << w[i][kolumna] << "\n";
		            plik.flush();
		        }
		        plik.close();
		    }
}

void zapisz(double** wyniki,int size,string napis){
	zapiszNazwe(wyniki,size,0,"Babelkowe_"+napis+".txt");
	zapiszNazwe(wyniki,size,1,"Wstawianie_"+napis+".txt");
	zapiszNazwe(wyniki,size,2,"Kopiec_"+napis+".txt");
	zapiszNazwe(wyniki,size,3,"QuickSort_"+napis+".txt");
	zapiszNazwe(wyniki,size,4,"Ilosc_elementow.txt");
}

int main() {

//	int axis[]={10,50,100,500,1000,5000,10000,20000,30000};
//	int liczb_prob=9;

	int liczb_prob=100;
	int* axis=new int[liczb_prob];

	for(int i=1;i<=liczb_prob;i++){
		axis[i]=i*1000;
	}


	double** wyniki=new double*[liczb_prob];
	for(int i=0;i<liczb_prob;i++){
		wyniki[i]=sprawdzwydajnosc(axis[i]);
	}
	zapisz(wyniki,liczb_prob,"losowy");

	double** wynikiOd=new double*[liczb_prob];
		for(int i=0;i<liczb_prob;i++){
			wynikiOd[i]=sprawdzwydajnoscOdwrotnie(axis[i]);
		}
	zapisz(wynikiOd,liczb_prob,"odwrotna");

	cout << "\n\nSortowanie dla losowych elementow: \n";
	for(int i=0;i<liczb_prob;i++){
		for(int j=0;j<5;j++){
			cout << wyniki[i][j] << ", ";
		}
		cout << endl;
	}

	cout << "\n\nSortowanie dla odwrotniej kolejnosci elementow: \n";
		for(int i=0;i<liczb_prob;i++){
			for(int j=0;j<5;j++){
				cout << wynikiOd[i][j] << ", ";
			}
			cout << endl;
		}

}
